/******************************************************************************
*
*   Filename    : drtc.c
*   Author      : Ariff Ehsan
*   Date        : Oct. 27, 2009
*   Description : Driver for Primer2 real-time clock (RTC).
*                 Code is modified from Cirlce RTC API for freeRTOS
*                 implementation.
*
******************************************************************************/

#include "FreeRTOS.h"
#include "semphr.h"

#include "drtc.h"

xSemaphoreHandle rtc_xSemaphore;

void RTC_Configuration( void )
    {
    /* create mutex semaphore for resource control */
    rtc_xSemaphore = xSemaphoreCreateMutex();
    
    /* CK_RTC clock selection */
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE );

    /* Allow access to BKP Domain */
    PWR_BackupAccessCmd( ENABLE );

    /* Enable the LSE OSC */
    RCC_LSEConfig( RCC_LSE_ON );
    /* Disable the LSI OSC */
    RCC_LSICmd( DISABLE );

    /* Select the RTC Clock Source */
    RCC_RTCCLKConfig( RCC_RTCCLKSource_LSE );

    /* Enable the RTC Clock */
    RCC_RTCCLKCmd( ENABLE );

#ifndef BUG_RTC_CRYSTAL
    /* Wait for RTC registers synchronization */
    RTC_WaitForSynchro();
#endif

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();

    /* Enable the RTC Second interrupt */
    RTC_ITConfig( RTC_IT_SEC, ENABLE );

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();

    /* Set RTC prescaler: set RTC period to 1sec */
    /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
    RTC_SetPrescaler( 32767 );

#ifndef BUG_RTC_CRYSTAL
    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
#endif
    }

void RTC_SetTime( u32 hh, u32 mm, u32 ss )
    {
    xSemaphoreTake( rtc_xSemaphore, ( portTickType ) portMAX_DELAY );
    
    /* Adjust the counter value */
    RTC_SetCounter( hh * 3600 + mm * 60 + ss );
    
    xSemaphoreGive( rtc_xSemaphore );
    }

void RTC_GetTime( u32* hh, u32* mm, u32* ss )
    {
    xSemaphoreTake( rtc_xSemaphore, ( portTickType ) portMAX_DELAY );
    
    u32 Tmp;
    
    /* Load the Counter value */
    Tmp = RTC_GetCounter();

    /* Compute  hours */
    *hh = ( Tmp / 3600 ) % 24;

    /* Compute minutes */
    *mm = ( Tmp / 60 ) % 60;

    /* Compute seconds */
    *ss = Tmp % 60;
    
    xSemaphoreGive( rtc_xSemaphore );
    }

